//*********************************************************************
//		Copyright (c) 2003 - 2008 Microsoft Corporation.
//      This code is provided under Microsoft Public License, which can be found at
//      http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx 
//
// @File: PerfMgr.cs
//
// Purpose: Manages collection
//
//
//
// Notes: 
//
//
//	
// History: 
//     @Version: V2.1
//
//     10/31/08 PGV 2.1.001.0 Starting V2.1 (based on 2.0.002.0 code)
//
//
// @EndHeader@
//*********************************************************************

using System;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.IO;
using System.ComponentModel;
using System.Globalization;

namespace PerfService
{
	public class CollectorThread 
	{
		Collector m_col;
		Thread m_thread;

		public CollectorThread (Collector collector)
		{
            m_col = collector;
			ThreadStart ts = new ThreadStart (m_col.Collect);
			m_thread = new Thread (ts);
		}

		public void Start ()
		{
			m_thread.Start ();
		}

		public void Stop ()
		{
            m_col.Deactivate ();
		}

		public void Abort ()
		{
			m_thread.Abort ();
		}
	}
    
	public class PerfMgr
	{
        public static Queue ResultQueue;
		ArrayList Collectors;
		Recorder m_recorder;
		Thread m_recorder_thread;
        string iniFileName;

		public PerfMgr (string iniFileName)
		{
            this.iniFileName = iniFileName;
            ResultQueue = Queue.Synchronized (new Queue (512));
			Collectors = new ArrayList ();
			m_recorder = new Recorder ();
		}

		public void Init ()
		{
            Configurator.ReadConfig (this, this.iniFileName);

			if (!Directory.Exists (Constants.OutputDir))
			{
				Directory.CreateDirectory (Constants.OutputDir);
			}

			m_recorder.Init ();
		}

		public void AddCollector (Collector collector)
		{
            Collectors.Add (new CollectorThread (collector));
		}

		public void Start ()
		{
			foreach (CollectorThread ct in Collectors)
			{
				ct.Start ();
			}

			m_recorder_thread = new Thread (new ThreadStart (m_recorder.Run));
			if (Constants.UseInvariantCulture)
			{
				m_recorder_thread.CurrentCulture = CultureInfo.InvariantCulture;
			}
			m_recorder_thread.Start ();
			SQLH2PerfCollector.Log ("SQLH2PerfCollector started", EventLogEntryType.Information, 2); 

		}

		public void Stop ()
		{
			foreach (CollectorThread ct in Collectors)
			{
				ct.Stop ();
			}
            m_recorder.Stop ();
			Debug.Flush ();
			Debug.Close ();
		}

		public void Shutdown ()
		{
            m_recorder.Stop ();
			SQLH2PerfCollector.Log ("SQLH2PerfCollector received ShutDown request"+Environment.NewLine
				+"Current workfile: "+m_recorder.FileName, EventLogEntryType.Information, 5); 
			foreach (CollectorThread ct in Collectors)
			{
				ct.Abort ();
			}

		}
	}

	#region DUMPER class to debug PerfCounter Win32 exceptions
//	public class Dumper 
//	{
//		public static void DumpException (Win32Exception wex, string msg)
//		{
//			if (wex.NativeErrorCode == 5 || wex.NativeErrorCode == 53 || wex.NativeErrorCode == 1726) return;
//
//			int i=0;
//			string name,
//				bname;
//
//			name = Constants.OutputDir+"\\dump"+DateTime.Now.ToString ("MMddyyHHmmss");
//			bname = name;
//			name += ".txt";
//
//			while (File.Exists (name) && i<Constants.FileNameResolutionAttempts) 
//			{
//				name = bname+"_"+i.ToString ()+".txt";
//				++i;
//			}
//			if (i == Constants.FileNameResolutionAttempts) return;
//
//			FileStream m_file = new FileStream (name, FileMode.Create, FileAccess.Write);
//			StreamWriter m_stream = new StreamWriter (m_file);
//			m_stream.WriteLine ("SQLH2PerfCollector dump file "+DateTime.Now);
//			m_stream.WriteLine (msg);
//
//			m_stream.WriteLine ("Error: "+wex.ErrorCode);
//			m_stream.WriteLine ("NativeError: "+wex.NativeErrorCode);
//			m_stream.WriteLine ("Message: "+wex.Message);
//			m_stream.WriteLine ("Source: "+wex.Source);
//			m_stream.WriteLine ("TargetSite: "+wex.TargetSite);
//			m_stream.WriteLine ("Stack Trace:");
//			m_stream.WriteLine (wex.StackTrace);
//
//			m_stream.Flush ();
//			m_stream.Close ();
//		}
//	}
	#endregion
}
